﻿namespace MhAdmin.System;

/// <summary>
/// 数据权限仓储模式对象
/// </summary>
/// <typeparam name="T"></typeparam>
public class DataRepository<T> : DbRepository<T> where T : DataEntityBase, new()
{
    private readonly ISysUserService _sysUserService;

    public DataRepository(ISysUserService sysUserService)
    {
        _sysUserService = sysUserService;
    }

    /// <summary>
    /// 获取数据权限查询条件
    /// </summary>
    /// <typeparam name="Y"></typeparam>
    /// <returns></returns>
    public async Task<Expressionable<Y>> GetDataQuery<Y>() where Y : DataEntityBase, new()
    {
        //获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();
        //动态查询条件,如果是连表查询,里面的it要改成连表里对应的别名
        var exp = Expressionable.Create<Y>();
        //用户机构在数据范围内
        exp.AndIF(dataScope is { Count: > 0 }, it => dataScope.Contains(it.CreateOrgId));
        //默认创建者ID等于自己,根据实际情况修改条件
        exp.AndIF(dataScope is { Count: 0 }, it => it.CreateUserId == UserManager.UserId);

        return exp;
    }

    /// <summary>
    /// 获取数据权限查询条件
    /// </summary>
    /// <returns></returns>
    public async Task<Expressionable<T>> GetDataQuery()
    {
        //获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();
        //动态查询条件,如果是连表查询,里面的it要改成连表里对应的别名
        var exp = Expressionable.Create<T>();
        //用户机构在数据范围内
        exp.AndIF(dataScope is { Count: > 0 }, it => dataScope.Contains(it.CreateOrgId));
        //默认创建者ID等于自己,根据实际情况修改条件
        exp.AndIF(dataScope is { Count: 0 }, it => it.CreateUserId == UserManager.UserId);

        return exp;
    }

    /// <summary>
    /// 判断是否有数据权限
    /// </summary>
    /// <param name="info">数据信息</param>
    /// <returns></returns>
    public async Task<bool> HavePermission(List<DataEntityModel> info)
    {
        // 获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();

        // 是否配置权限
        if (dataScope.Count > 0)
        {
            // 这里需要满足两种判定，一个是 不包含在权限内的数据，同时这个数据还不是自己创建的;
            bool has = info.Any(x => !dataScope.Contains(x.CreateOrgId) && x.CreateUserId != UserManager.UserId);
            if (has) throw Oops.Bah(ErrorCodeEnum.A0004);
            return true;
        }
        else
        {
            return true;
        }
    }

    /// <summary>
    /// 判断是否有数据权限
    /// </summary>
    /// <param name="info">数据信息</param>
    /// <returns></returns>
    public async Task<bool> HavePermission(DataEntityModel info)
    {
        // 获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();

        // 是否配置权限
        if (dataScope.Count > 0)
        {
            // 这里需要满足两种判定，一个是 不包含在权限内的数据，同时这个数据还不是自己创建的;
            bool has = !dataScope.Contains(info.CreateOrgId) && info.CreateUserId != UserManager.UserId;
            if (has) throw Oops.Bah(ErrorCodeEnum.A0004);
            return true;
        }
        else
        {
            return true;
        }
    }

    /// <summary>
    /// 判断是否有数据权限
    /// </summary>
    /// <param name="ids">数据Id</param>
    /// <returns></returns>
    public async Task<bool> HavePermissionById<Y>(List<long> ids) where Y : DataEntityBase, new()
    {
        // 获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();

        // 查询出所有数据
        var rules = await Context.Queryable<Y>().Where(it => ids.Contains(it.Id)).Select(it => new MsgMail { CreateOrgId = it.CreateOrgId, CreateUserId = it.CreateUserId }).ToListAsync();//根据ID获取机构ID和创建者ID

        // 是否配置权限
        if (dataScope.Count > 0)
        {
            // 这里需要满足两种判定，一个是 不包含在权限内的数据，同时这个数据还不是自己创建的;
            bool has = rules.Any(x => !dataScope.Contains(x.CreateOrgId) && x.CreateUserId != UserManager.UserId);
            if (has) throw Oops.Bah(ErrorCodeEnum.A0004);
            return true;
        }
        else
        {
            return true;
        }
    }

    /// <summary>
    /// 判断是否有数据权限
    /// </summary>
    /// <param name="id">数据Id</param>
    /// <returns></returns>
    public async Task<bool> HavePermissionById<Y>(long id) where Y : DataEntityBase, new()
    {
        // 获取数据范围
        var dataScope = await _sysUserService.GetLoginUserApiDataScope();

        // 查询出所有数据
        var cur = await Context.Queryable<Y>().Where(it => it.Id == id).Select(it => new MsgMail { CreateOrgId = it.CreateOrgId, CreateUserId = it.CreateUserId }).FirstAsync();//根据ID获取机构ID和创建者ID

        // 是否配置权限
        if (dataScope.Count > 0)
        {
            // 这里需要满足两种判定，一个是 不包含在权限内的数据，同时这个数据还不是自己创建的;
            bool has = !dataScope.Contains(cur.CreateOrgId) && cur.CreateUserId != UserManager.UserId;
            if (has) throw Oops.Bah(ErrorCodeEnum.A0004);
            return true;
        }
        else
        {
            return true;
        }
    }

    /// <summary>
    /// 创建实体模型
    /// </summary>
    public class DataEntityModel
    {
        /// <summary>
        /// 创建部门Id
        /// </summary>
        public long CreateOrgId { get; set; }

        /// <summary>
        /// 创建用户Id
        /// </summary>
        public long CreateUserId { get; set; }
    }
}
